/**
 * @Copyright ®2015 Sinosoft Co. Ltd. All rights reserved.<br/>
 * 项目名称 : 中科软支付平台
 * 创建日期 : 2016年12月22日
 * 修改历史 : 
 *     1. [2016年12月22日]创建文件 by liuyujia
 */
package com.sinosoft.sinopay.web.agentpay.web.controller;

import java.io.IOException;
import java.math.BigDecimal;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.fastjson.JSON;
import com.sinosoft.sinocloud.common.config.ENUM_REPORTLOG_DEALTYPE;
import com.sinosoft.sinocloud.common.config.ENUM_REPORTLOG_REPORTTYPE;
import com.sinosoft.sinocloud.common.config.ENUM_REPORTLOG_STATE;
import com.sinosoft.sinocloud.common.dto.ReportLogDTO;
import com.sinosoft.sinocloud.platform.base.SinoBaseController;
import com.sinosoft.sinocloud.platform.common.exception.biz.BizDataErrException;
import com.sinosoft.sinocloud.platform.common.exception.biz.IllegalRequestException;
import com.sinosoft.sinocloud.platform.common.exception.biz.SinoBizException;
import com.sinosoft.sinocloud.platform.common.exception.checked.RepeatRequestException;
import com.sinosoft.sinocloud.platform.common.exception.system.SinoSystemException;
import com.sinosoft.sinocloud.platform.common.util.SecurityUtil;
import com.sinosoft.sinopay.payrules.config.ENUM_PAY_TYPE;
import com.sinosoft.sinopay.payrules.dto.MerchantCheckDTO;
import com.sinosoft.sinopay.web.agentpay.biz.config.AgentPaymentConstants;
import com.sinosoft.sinopay.web.agentpay.biz.config.ENUM_REPORT_BIZTYPE;
import com.sinosoft.sinopay.web.agentpay.biz.service.AgentSecurityService;
import com.sinosoft.sinopay.web.agentpay.biz.service.PaymentAgentService;
import com.sinosoft.sinopay.web.agentpay.config.ENUM_PAY_RET;
import com.sinosoft.sinopay.web.agentpay.dto.AgentEntryRequsetDTO;
import com.sinosoft.sinopay.web.agentpay.dto.AgentEntryResponseDTO;

/**  
 * 【代理网关支付请求入口Controller】
 * @author liuyujia
 * @date 2016年12月22日 上午11:07:48 
 * @version V1.0  
 */
@Controller
@RequestMapping("/sinopay/agentOrderPay")
public class AgentOrderPayController extends SinoBaseController{
	@Autowired
	private AgentSecurityService agentSecurityService;
	@Autowired
	private PaymentAgentService paymentAgentService;

	@RequestMapping(value = "agentRequest.do")
	public void getTongOrderUrl(HttpServletRequest request, HttpServletResponse response){
		//1.接收请求参数
		String tPayData = request.getParameter("pay_data");
    	String tSignMsg = request.getParameter("sign_msg");
    	String tRequestIp = getRemortIP(request);
    	ReportLogDTO tReportLogDTO = new ReportLogDTO();//定义日志对象
    	//返回信息定义
    	//返回信息定义
    	AgentEntryResponseDTO tAgentEntryResponseDTO = new AgentEntryResponseDTO();
    	try{
    		//2.请求信息解密
			String tDecodeData = SecurityUtil.aesDecrypt(tPayData, AgentPaymentConstants.REPORT_ENCRY_KEY);
			//3.解析报文
			AgentEntryRequsetDTO tAgentEntryRequsetDTO = JSON.parseObject(tDecodeData, AgentEntryRequsetDTO.class);
			//4.验证请求合法性
			//4.1 验证签名合法性
			String tMerchantCode = tAgentEntryRequsetDTO.getMerchantCode();
			agentSecurityService.checkMerchantSignValid(tMerchantCode, tAgentEntryRequsetDTO, tSignMsg);
			//4.2 验证请求IP合法性
			agentSecurityService.checkRequestIpValid(tRequestIp);
			//4.3 调用规则服务，进行支付规则校验
			MerchantCheckDTO merchantCheckDTO = new MerchantCheckDTO();
			merchantCheckDTO.setMerchantCode(tAgentEntryRequsetDTO.getMerchantCode());
			merchantCheckDTO.setPayAmount(tAgentEntryRequsetDTO.getPayAmount());
			merchantCheckDTO.setPayType(ENUM_PAY_TYPE.AGENTPAY.code());//代理网关支付
			//TODO  支付规则校验
//			wechatSecurityService.checkMerchantRules(merchantCheckDTO);
			//5.生成报文日志对象
			tReportLogDTO.setBusinessType(ENUM_REPORT_BIZTYPE.PAY_ORDER_REQ.code());
			tReportLogDTO.setSourceCode(tAgentEntryRequsetDTO.getMerchantCode());
			tReportLogDTO.setRequestIp(tRequestIp);
			tReportLogDTO.setRequestXml(tDecodeData);
			tReportLogDTO.setReportType(ENUM_REPORTLOG_REPORTTYPE.RECEIVE.code());
			tReportLogDTO.setSerialNo(tAgentEntryRequsetDTO.getSerialNo());
			tReportLogDTO.setOrderBizNo(tAgentEntryRequsetDTO.getBizNo());
			tReportLogDTO.setDealType(ENUM_REPORTLOG_DEALTYPE.SYNC_DEAL.code());
			tReportLogDTO.setDescription(tAgentEntryRequsetDTO.getTransDesc());
			tReportLogDTO.setCallbackUrl("");
			//6.校验订单重复性
			String tSerialNo = tAgentEntryRequsetDTO.getSerialNo();
			String tPayAmountStr =  tAgentEntryRequsetDTO.getPayAmount().setScale(2, BigDecimal.ROUND_HALF_DOWN).toString();
			agentSecurityService.checkRepeatRequest(tMerchantCode,tSerialNo);
			//7.生成支付URL
			String payUrl = paymentAgentService.dealWechatPayRequest(tAgentEntryRequsetDTO);
			//8.返回支付地址
			logger.info("返回支付地址："+payUrl);
			tReportLogDTO.setState(ENUM_REPORTLOG_STATE.SUCC.code());
			tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_SUCCESS.code());
			tAgentEntryResponseDTO.setRetMsg(ENUM_PAY_RET.PAY_RET_SUCCESS.desc());
			tAgentEntryResponseDTO.setAgentMainUrl(payUrl);
    	}
    	catch(BizDataErrException ex){
			logger.error(ex.getStackTrace());
			tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg(ex.getMessage());
			tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
			tReportLogDTO.setDescription(ex.getMessage());
		}
		catch(RepeatRequestException ex){
    		logger.error(ex.getStackTrace());
	     	tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
	     	tReportLogDTO.setDescription(ex.getMessage());
	     	tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg(ex.getMessage());
    	}
    	catch(IllegalRequestException ex){
    		logger.error(ex.getStackTrace());
	     	tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
	     	tReportLogDTO.setDescription(ex.getMessage());
	     	tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg("非法支付请求！");
    	}
    	catch(SinoBizException ex){
    		logger.error(ex.getStackTrace());
	     	tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
	     	tReportLogDTO.setDescription(ex.getMessage());
	     	tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg(ex.getMessage());
    	}
    	catch(SinoSystemException ex){
    		logger.error(ex.getStackTrace());
	     	tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
	     	tReportLogDTO.setDescription(ex.getMessage());
	     	tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg("系统异常，请联系管理员!");
    	}
    	catch(Exception ex){
    		logger.error(ex.getStackTrace());
	     	tReportLogDTO.setState(ENUM_REPORTLOG_STATE.EXCEPTION.code());
	     	tReportLogDTO.setDescription(ex.getMessage());
	     	tAgentEntryResponseDTO.setRetCode(ENUM_PAY_RET.PAY_RET_FAIL.code());
			tAgentEntryResponseDTO.setRetMsg("系统未知异常，请联系管理员!");
    	}
		finally{
    		//8.持久化报文
			try {
//				response.setContentType("text/html");
				response.setCharacterEncoding("UTF-8");
				response.setHeader("Content-type", "text/html;charset=GBK");
				response.getWriter().print(JSON.toJSONString(tAgentEntryResponseDTO));
			} catch (IOException e) {
				logger.error(e.getStackTrace());
			}
    	}
	}

	/**
	 * 获取请求IP地址
	 * @param request
	 * @return
	 */
	private String getRemortIP(HttpServletRequest request) {
		if (request.getHeader("x-forwarded-for") == null) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for");
	}
}
